//implement ACETimerImpl
//andycai_sc 2011-05-28

#include "GParallel/GAce/ACETimerImpl.h"
#include <ace/Timer_Hash.h>

ACETimerImpl::ACETimerImpl(GTimer* timer) : GTimerImpl(timer), m_timerId(0),
m_aceTimerRef(ACETimerImpl::getTimerRef())
{
}

ACETimerImpl::~ACETimerImpl()
{
	ACETimerImpl::freeTimerRef(m_aceTimerRef);
}

void ACETimerImpl::beginImpl(long millisc)
{
	ACE_Time_Value interv(0, millisc * 1000);
	ACE_Time_Value future(ACE_OS::gettimeofday());
	future += interv;
	m_timerId = m_aceTimerRef->m_timer->schedule(&m_timerEventHandler,
		(void*)this, future, interv);
}

void ACETimerImpl::cancelImpl()
{
	m_aceTimerRef->m_timer->cancel(m_timerId);
}

ACETimerImpl::ACETimerRefCounter::ACETimerRefCounter() : m_refCount(0)
{
	m_timer = new ACE_Timer_Hash;
}

ACETimerImpl::ACETimerRefCounter::~ACETimerRefCounter()
{
	delete m_timer;
}

void ACETimerImpl::ACETimerRefCounter::addReference()
{
	m_refMutex.lock();
	++m_refCount;
	m_refMutex.release();
}

long ACETimerImpl::ACETimerRefCounter::decReference()
{
	m_refMutex.lock();
	long count = --m_refCount;
	m_refMutex.release();
	return count;
}

static ACE_Thread_Mutex refCounterMutex;

ACETimerImpl::ACETimerRefCounter*& ACETimerImpl::getTimerRef()
{
	refCounterMutex.lock();
	static ACETimerRefCounter* timerRef = 0;
	if (timerRef == 0)
		timerRef = new ACETimerRefCounter;
	refCounterMutex.release();
	timerRef->addReference();
	return timerRef;
}

void ACETimerImpl::freeTimerRef(ACETimerRefCounter*& timerRef)
{
	refCounterMutex.lock();
	if (timerRef->decReference() == 0)
	{
		delete timerRef;
		timerRef = 0;
	}
	refCounterMutex.release();
}

ACETimerImpl::TimerEventHandler::TimerEventHandler()
{
}

ACETimerImpl::TimerEventHandler::~TimerEventHandler()
{
}

int ACETimerImpl::TimerEventHandler::handle_timeout(const ACE_Time_Value &, const void *arg)
{
	ACETimerImpl* timerImpl = (ACETimerImpl*)arg;
	timerImpl->exec();
	return 0;
}

GTimerImpl* createTimerFromAce(GTimer* timer)
{
	return new ACETimerImpl(timer);
}
